package org.hamster.common;

/**
 * Utility class for handling both IPv4 and IPv6 addresses.
 * Provides methods to check if an IP address is within a given range.
 */
public class IPUtil {
    
    /**
     * Checks if the given IP address is within the range represented by the mask string.
     * Automatically determines whether to use IPv4 or IPv6 based on the format of the IP address.
     * 
     * @param mask the IP mask string (e.g. "192.168.1.0/24" or "2001:db8::/32")
     * @param ip the IP address to check
     * @return true if the IP is valid and within range, false otherwise
     * @throws IllegalArgumentException if the mask string is not valid
     */
    public static boolean inRange(String mask, String ip) {
        if (mask == null || mask.isEmpty()) {
            throw new IllegalArgumentException("Mask string cannot be null or empty");
        }
        
        if (ip == null || ip.isEmpty()) {
            return false;
        }
        
        // Determine if we're dealing with IPv4 or IPv6 based on the IP address
        if (IPValidationUtil.isIPv6Address(ip)) {
            try {
                IPv6Mask ipv6Mask = new IPv6Mask(mask);
                return ipv6Mask.inRange(ip);
            } catch (Exception e) {
                // If IPv6 mask creation fails, try IPv4 as fallback
                try {
                    IPv4Mask ipv4Mask = new IPv4Mask(mask);
                    return ipv4Mask.inRange(ip);
                } catch (Exception e2) {
                    return false;
                }
            }
        } else if (IPValidationUtil.isIPv4Address(ip)) {
            try {
                IPv4Mask ipv4Mask = new IPv4Mask(mask);
                return ipv4Mask.inRange(ip);
            } catch (Exception e) {
                // If IPv4 mask creation fails, try IPv6 as fallback
                try {
                    IPv6Mask ipv6Mask = new IPv6Mask(mask);
                    return ipv6Mask.inRange(ip);
                } catch (Exception e2) {
                    return false;
                }
            }
        } else {
            // Invalid IP format
            return false;
        }
    }
    
    /**
     * Creates an IPMaskable instance appropriate for the given mask string.
     * Attempts to determine the type based on common patterns, but the resulting
     * mask may not be compatible with all IP addresses.
     * 
     * @param mask the IP mask string (e.g. "192.168.1.0/24" or "2001:db8::/32")
     * @return an IPMaskable instance (either IPv4Mask or IPv6Mask)
     * @throws IllegalArgumentException if the mask string is not valid
     */
    public static IPMaskable createMask(String mask) {
        if (mask == null || mask.isEmpty()) {
            throw new IllegalArgumentException("Mask string cannot be null or empty");
        }
        
        // Try to determine from the mask format itself
        if (mask.contains(":")) {
            return new IPv6Mask(mask);
        } else {
            return new IPv4Mask(mask);
        }
    }
    
    /**
     * Validates if the given string is a valid IPv4 address.
     * 
     * @param ip the IP address string to validate
     * @return true if the IP is a valid IPv4 address, false otherwise
     */
    public static boolean isValidIPv4(String ip) {
        return IPValidationUtil.isValidIPv4(ip);
    }
    
    /**
     * Validates if the given string is a valid IPv6 address.
     * 
     * @param ip the IP address string to validate
     * @return true if the IP is a valid IPv6 address, false otherwise
     */
    public static boolean isValidIPv6(String ip) {
        return IPValidationUtil.isValidIPv6(ip);
    }
}